package net.wzw.service.impl;

import com.alibaba.fastjson.JSON;
import net.wzw.constants.HomeConstant;
import net.wzw.entity.RecipesInfoEntity;
import net.wzw.entity.RecipesRequestEntity;
import net.wzw.entity.RecommendFeedEntity;
import net.wzw.service.HomeCommonService;
import net.wzw.service.HomeFeedService;
import net.wzw.vo.RecipesListResultVO;
import lombok.extern.slf4j.Slf4j;
import net.wzw.redis.RedisCache;
import net.wzw.utils.PageUtil;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author wzw
 * @date 2025/4/16
 * @Description 首页Feed流实现类
 */
@Service
@Slf4j
public class HomeFeedServiceImpl implements HomeFeedService {

    @Autowired
    private HomeCommonService homeCommonService;

    @Autowired
    private RedisCache redisCache;

    /*** 获取首页Feed流信息
     * Description: 首页feed流核心处理逻辑 1.根据用户id 判断是否命中推荐 2.命中推荐则走推荐内容(大数据中台),否则走本地缓存
     * @param
     * @Return: {@link null}
     * @Author: Administrator
     * @Date: 2025/4/16 10:53
     */
    @Override
    public RecipesListResultVO getHomeFeedRecipesList(RecipesRequestEntity recipesRequestEntity) {

        RecipesListResultVO recipesListResultVO;

        //判断用户id是否命中缓存
        Boolean isRecommendMatch  = homeCommonService.isMatchRecommend(recipesRequestEntity.getUserId());

        if(isRecommendMatch){
           //如果命中则获取推荐

            recipesListResultVO = getRecommendRecipesList( recipesRequestEntity );

        }else {

            //如果没有命中或者数据中台接口挂了则获取本地缓存
            recipesListResultVO = getCacheRecipesList(recipesRequestEntity);

        }

        log.info("首页feed 流获取，userId,是否命中推荐:{},feed流内容:{}",recipesRequestEntity.getUserId(),isRecommendMatch,recipesListResultVO);

        if(Objects.nonNull(recipesListResultVO) && !CollectionUtils.isEmpty(recipesListResultVO.getRecipesInfoResultVOList())){

             return  recipesListResultVO;
        }

        return null;
    }

    /**
     * 生成本地食谱缓存列表
     *
     * **/
    @Override
    public List<RecipesInfoEntity> generatorFeed() {

        //获取食谱信息集合
        List<RecipesInfoEntity> list = homeCommonService.getFeedRecipes();
        log.info("生成feed流信息:{}",list);
        //写入数据到缓存中 1.首页feed流中存储的食谱ID集合
        String feedVersion = String.valueOf(System.currentTimeMillis());
        //获取食谱id集合列表
        List<Long> recipesIdList = list.stream().map(RecipesInfoEntity::getId).collect(Collectors.toList());
        //设置首页feed流id集合
        redisCache.rPushAll(String.format(HomeConstant.HOME_FEED_PREFIX,feedVersion),recipesIdList.stream().map(Object::toString).toArray(String[]::new));
        //首页feed流最新版本号
        redisCache.set(HomeConstant.HOME_FEED_LATEST_VERSION_PREFIX,feedVersion,0);
        //2.首页食谱信息缓存
        for(RecipesInfoEntity recipesInfoEntity : list){

            //设置食谱缓存 id -> info
            redisCache.putIfAbsent(HomeConstant.RECIPES_INFO_PREFIX,String.valueOf(recipesInfoEntity.getId()), JSON.toJSONString(recipesInfoEntity));

        }


        return list;
    }

    /**
     * 从本地缓存进行获取食谱信息
     * **/
    private RecipesListResultVO getCacheRecipesList(RecipesRequestEntity recipesRequestEntity){

          List<String> recipesIdList;

          String feedVersion  = recipesRequestEntity.getFeedVersion();

          Integer page = recipesRequestEntity.getPage();

          Boolean pullRefresh = recipesRequestEntity.getPullRefresh();

          //判断是否已经缓存过首页feed流
           Boolean isHomeFeedCached = isHomeFeedCached(feedVersion);

           if(!isHomeFeedCached){
               //如果没有则获取最新的版本号
               feedVersion = getHomeFeedLatestVersion();

           }
           //如果有则[下拉刷新]，获取随机范围页码
          if(pullRefresh){

             page =  RandomUtils.nextInt(HomeConstant.PULL_PEFRESH_PAGE_START,HomeConstant.PULL_PEFRESH_PAGE_END);

          }else{
              //否则从0开始
              page = HomeConstant.PAGE_START;

          }
          //从redis 分页获取feed流混村
          recipesIdList =  getHomeFeedFromCacheByVersionAndPage(feedVersion,page);

          //判断是否存在下一页
          boolean hasNextPage = false;

          if(!CollectionUtils.isEmpty(recipesIdList)){

              Long total = getHomeFeedSizeFromCacheByVersion(feedVersion);
              //缓存不为空
              if(Objects.nonNull(total) && total.intValue() >0){

                  //计算是否有下一页缓存数据
                  hasNextPage = PageUtil.hasNextPage(total.intValue(),page,recipesRequestEntity.getPageSize());

              }

          }

          // 获取食谱缓存信息
          List<RecipesInfoEntity> list =  getRecipesListFromCache(recipesIdList);


          return null;

    }


    /*
     * Description: 从Redis 获取feed 流缓存大小
     * @param null
     * @Return: {@link null}
     * @Author: Administrator
     * @Date: 2025/4/17 18:05
     */
    private Long getHomeFeedSizeFromCacheByVersion(String feedVersion){

        if(StringUtils.isBlank(feedVersion)){

            //为空
            return 0L;


        }
        String key = String.format(HomeConstant.HOME_FEED_PREFIX,feedVersion);

        return  redisCache.lsize(key);

    }


     /**
      * Description: 检测是否已经缓存过首页feed流
      * @param
      * @Return: {@link null}
      * @Author: Administrator
      * @Date: 2025/4/16 15:14
      */
     private Boolean isHomeFeedCached(String feedVersion){

         if(StringUtils.isNotBlank(feedVersion)){

             return false;

         }
         //监测是否已经缓存过
         return redisCache.hasKey(String.format(HomeConstant.HOME_FEED_PREFIX,feedVersion));

     }

     /**
      * 获取首页feed流最新版本号
      * **/
     private String getHomeFeedLatestVersion(){

         return redisCache.get(HomeConstant.HOME_FEED_LATEST_VERSION_PREFIX);

     }
    /**
     * 从Redis 分页获取feed流缓存
     */
    private List<String> getHomeFeedFromCacheByVersionAndPage(String feedVersion,Integer page){

        //如果版本号为空则返回空list
        if(StringUtils.isBlank(feedVersion)){

            return Lists.newArrayList();

        }

        //处理最小页码
        if(page < HomeConstant.PAGE_START){

            page = HomeConstant.PAGE_START;

        }
        //feed流缓存key
        String key = String.format(HomeConstant.HOME_FEED_PREFIX,feedVersion);
        //计算开始位置和结束位置
       int start = PageUtil.startPagePosition(page,HomeConstant.DEFAULT_PAGE_SIZE);
       int end = PageUtil.endPageRedisPosition(page,HomeConstant.DEFAULT_PAGE_SIZE);
        //从 redis List中获取feed流缓存数据
       List<String> recipesIdList =  redisCache.lRange(key,start,end);

       if(CollectionUtils.isEmpty(recipesIdList)){

           return  Lists.newArrayList();

       }
       return recipesIdList;


    }


    /*
     * Description:  从推荐系统进行获取
     * @param null
     * @Return: {@link null}
     * @Author: Administrator
     * @Date: 2025/4/17 17:48
     */
    private RecipesListResultVO getRecommendRecipesList (RecipesRequestEntity recipesRequestEntity){

        //获取推荐的食谱id列表
        RecommendFeedEntity recommendFeedEntity = homeCommonService.getRecommendRecipes(recipesRequestEntity);
        log.info("首页feed 流模块-获取推荐食谱id列表信息:{}",recommendFeedEntity);
        if(Objects.isNull(recommendFeedEntity)){
            return  null;
        }
        //获取食谱缓存信息
        List<RecipesInfoEntity>  list = getRecipesListFromCache(recommendFeedEntity.getRecipesIdList());

        //赋值并返回
        RecipesListResultVO recipesListResultVO = new RecipesListResultVO();
        recipesListResultVO.setCurrPage(recipesRequestEntity.getPage());
        recipesListResultVO.setHasNextPage(recommendFeedEntity.getHasNextPage());
        recipesListResultVO.setRecipesInfoResultVOList(list);
        return recipesListResultVO;

    }

    /*
     * Description: 从缓存中批量获取feed流数据
     * @param null
     * @Return: {@link null}
     * @Author: Administrator
     * @Date: 2025/4/17 17:53
     */
    private List<RecipesInfoEntity> getRecipesListFromCache(List<String> recipesIdList){

        List<RecipesInfoEntity> list = new ArrayList<>();

        //判断参数是否为空
        if(CollectionUtils.isEmpty(recipesIdList)){

            return  list ;

        }
        //从缓存中批量获取feed流数据
        List<String>  cacheJsonList = redisCache.multiGet(HomeConstant.RECIPES_INFO_PREFIX,recipesIdList);
        //判断缓存是否为空
        if(CollectionUtils.isEmpty(cacheJsonList)){

            return  list;

        }

        for (String json :cacheJsonList)
        {
            //为空继续
            if(StringUtils.isBlank(json)){

                continue;
            }
            //将缓存数据赋值到对象中
            RecipesInfoEntity recipesInfoEntity = JSON.parseObject(json,RecipesInfoEntity.class);

            list.add(recipesInfoEntity);

        }

        return list;


    }

}

